using System.Runtime.CompilerServices;

//
// * Copyright (c) 2002-2009 "Neo Technology,"
// *     Network Engine for Objects in Lund AB [http://neotechnology.com]
// *
// * This file is part of Neo4j.
// * 
// * Neo4j is free software: you can redistribute it and/or modify
// * it under the terms of the GNU Affero General Public License as
// * published by the Free Software Foundation, either version 3 of the
// * License, or (at your option) any later version.
// * 
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU Affero General Public License for more details.
// * 
// * You should have received a copy of the GNU Affero General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// 
namespace org.neo4j.kernel.impl.core
{

	using Transaction = javax.transaction.Transaction;
	using TransactionManager = javax.transaction.TransactionManager;

	using Node = org.neo4j.graphdb.Node;
	using EmbeddedGraphDatabase = org.neo4j.kernel.EmbeddedGraphDatabase;
	using AbstractNeo4jTestCase = org.neo4j.kernel.impl.AbstractNeo4jTestCase;

	public class TestTxSuspendResume : AbstractNeo4jTestCase
	{
		public TestTxSuspendResume(string testName) : base(testName)
		{
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public void testMultipleTxSameThread() throws Exception
		public virtual void testMultipleTxSameThread()
		{
			EmbeddedGraphDatabase neo2 = new EmbeddedGraphDatabase(getStorePath("test-neo2"));
			TransactionManager tm = neo2.getConfig().getTxModule().getTxManager();
			tm.begin();
			Node refNode = neo2.getReferenceNode();
			Transaction tx1 = tm.suspend();
			tm.begin();
			refNode.setProperty("test2", "test");
			Transaction tx2 = tm.suspend();
			tm.resume(tx1);
			CommitThread thread = new CommitThread(tm, tx2);
			thread.Start();
		// would wait for ever since tx2 has write lock but now we have other
		// thread thread that will commit tx2
			refNode.removeProperty("test2");
			assertTrue(thread.success());
			tm.commit();
			neo2.shutdown();
		}

		private class CommitThread : Thread
		{
			private readonly TransactionManager tm;
			private readonly Transaction tx;
			private bool success = false;

			internal CommitThread(TransactionManager tm, Transaction tx)
			{
				this.tm = tm;
				this.tx = tx;
			}

			[MethodImpl(MethodImplOptions.Synchronized)]
			public override void run()
			{
				try
				{
					sleep(1000);
					tm.resume(tx);
					tm.commit();
					success = true;
				}
				catch (System.Exception t)
				{
					t.printStackTrace();
				}
			}

			[MethodImpl(MethodImplOptions.Synchronized)]
			internal virtual bool success()
			{
				return success;
			}
		}
	}
}